package com.justech.mes.utils;

import cn.hutool.core.bean.BeanUtil;

import java.lang.reflect.Field;
import java.util.Objects;

/**
 * @author feifei.li
 */
@SuppressWarnings("all")
public final class ObjectUtil {

    public static final boolean isNull(Object o) {
        return o == null;
    }

    public static final boolean isNulls(Object... os) {
        boolean falg = true;
        for (Object o : os) {
            if (!isNull(o)) {
                return false;
            }
        }
        return falg;
    }

    public static boolean isNull(Object... objects) {
        for (Object o : objects) {
            if (isNotNull(o)) {
                return false;
            }
        }
        return true;
    }

    public static final boolean isNotNull(Object o) {
        return !isNull(o);
    }

    public static final boolean isNotNull(Object... objects) {
        for (Object o : objects) {
            if (isNull(o)) {
                return false;
            }
        }
        return true;
    }

    public static <T> T copyProperties(Object source, T target) {
        MesAssert.isTrue((isNull(source) || isNull(target)), "source or target object must not null");
        Class<?> targetClass = target.getClass();
        Class<?> sourceClass = source.getClass();
        Field[] targetClassDeclaredFields = targetClass.getDeclaredFields();
        for (Field tf : targetClassDeclaredFields) {
            tf.setAccessible(true);
            Field sourceField = getField(sourceClass, tf.getName());
            Object o = get(source, sourceField);
            try {
                tf.set(target, o);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return target;
    }

    /**
     * 属性拷贝
     *
     * @param source
     * @param target
     * @param noJustGive 当源对象中的属性存在value的时候执行拷贝。
     * @param <T>
     * @return
     */
    public static <T> T copyProperties(Object source, T target, boolean noJustGive) {
        MesAssert.isTrue((isNull(source) || isNull(target)), "source or target object must not null");
        Class<?> targetClass = target.getClass();
        Class<?> sourceClass = source.getClass();
        Field[] targetClassDeclaredFields = targetClass.getDeclaredFields();
        for (Field tf : targetClassDeclaredFields) {
            tf.setAccessible(true);
            Field sourceField = getField(sourceClass, tf.getName());
            Object v = get(source, sourceField);
            if (noJustGive) {
                if (isNotNull(v)) {
                    Object s = new Object();
                    BeanUtil.copyProperties(v, s);
                    set(tf, target, s);
                }
            } else {
                set(tf, target, v);
            }
        }
        return target;
    }

    public static void set(Field f, Object target, Object v) {
        try {
            f.set(target, v);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static Object get(Object source, Field f) {
        Object val = null;
        f.setAccessible(true);
        try {
            val = f.get(source);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return val;
    }

    public static Field getField(Class<?> c, String fieldName) {
        try {
            return c.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }
}
